#ifndef _FSM_H_
#define _FSM_H_

/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
/* Public typedef ------------------------------------------------------------*/
enum ProcessEnum
{
    PROCESS_INIT = 0,
    PROCESS_IDLE,
    PROCESS_BEFORE_START,
    PROCESS_START,
    PROCESS_BEFORE_RUN,
    PROCESS_RUN,
    PROCESS_RUN_WAIT,
    PROCESS_BEFORE_FINISH,
    PROCESS_FINISH,
    PROCESS_LONG_WAIT,
    PROCESS_WAIT,
    PROCESS_RESET,
    PROCESS_RESET_WAIT,
    PROCESS_ERROR_TRIGGED,
    PROCESS_ERROR,
    PROCESS_LOCK,
    PROCESS_CONFIG,
};

struct Process
{ 
    int current;
    int last;
    uint32_t __time;
    void (*change)(struct Process *process);
};

/* Public variables ----------------------------------------------------------*/
/* Public define -------------------------------------------------------------*/
/* Public macro --------------------------------------------------------------*/
#define PROCESS_CHANGE(processObj, process)                     \
    {                                                           \
        processObj.last = processObj.current;                   \
        processObj.current = process;                           \
        if(processObj.change != NULL)                           \
        {   processObj.change(&processObj); }                   \
    }
    
#define PROCESS_CHANGE_WITH_TIME(processObj, process, time)     \
    {                                                           \
        processObj.last = processObj.current;                   \
        processObj.current = process;                           \
        processObj.__time = time;                               \
        if(processObj.change != NULL)                           \
        {   processObj.change(&processObj); }                   \
    }

#define PROCESS_RETURN(processObj)                              \
    {                                                           \
        uint32_t __processTemp;                                 \
        __processTemp = processObj.current;                     \
        processObj.current = processObj.last;                   \
        processObj.last = __processTemp;                        \
        if(processObj.change != NULL)                           \
        {   processObj.change(&processObj); }                   \
    }

#define PROCESS_RETURN_WITH_TIME(processObj, time)              \
    {                                                           \
        uint32_t __processTemp;                                 \
        __processTemp = processObj.current;                     \
        processObj.current = processObj.last;                   \
        processObj.last = __processTemp;                        \
        processObj.__time = time;                               \
        if(processObj.change != NULL)                           \
        {   processObj.change(&processObj); }                   \
    }
/* Public function prototypes ------------------------------------------------*/

#endif
